package com.hujing.springsource.a16;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

public class A16 {

    public static void main(String[] args) throws NoSuchMethodException {
        //定义切点,对T1中的foo()方法进行增强
        AspectJExpressionPointcut pt1 = new AspectJExpressionPointcut();
        pt1.setExpression("execution(* foo())");
        System.out.println(pt1.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println(pt1.matches(T1.class.getMethod("bar"), T1.class));

        //定义切点,对T1中的@Transactional注解标注的方法进行增强
        AspectJExpressionPointcut pt2 = new AspectJExpressionPointcut();
        pt2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
        System.out.println(pt2.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println(pt2.matches(T1.class.getMethod("bar"), T1.class));

        StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                //判断方法上是否有@Transactional注解
                if (method.isAnnotationPresent(Transactional.class)){
                    return true;
                }
                //判断类上是否有@Transactional注解
                MergedAnnotations annotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if (annotations.isPresent(Transactional.class)){
                    return true;
                }
                return false;
            }
        };

        System.out.println(pt3.matches(T1.class.getMethod("foo"), T1.class));
        System.out.println(pt3.matches(T2.class.getMethod("foo"), T2.class));
        System.out.println(pt3.matches(T3.class.getMethod("foo"), T3.class));
    }
    
    static class T1{
        @Transactional
        public void foo(){
        }
        
        public void bar(){
        }
    }
    
    @Transactional
    static class T2{
        public void foo(){}
        
        public void bar(){}
    }
    
    @Transactional
    interface I1{
        void foo();
        void bar();
    }
    
    static class T3 implements I1{

        @Override
        public void foo() {
            
        }

        @Override
        public void bar() {

        }
    }
}
